package com.android.systemui.ios.wall;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
import android.widget.Scroller;

import com.android.systemui.ios.Constants;
import com.android.systemui.ios.R;

public class IpKeyguardScrollView extends LinearLayout {

    private OnPageChangedListener mPageChangedListener;

    private final int PAGE_WIDGET = 0;
    private final int PAGE_NORMAL = 1;
    private final int PAGE_CAMERA = 2;

    private final int DIR_UNKNOWN = 0;
    private final int DIR_LEFT_RIGHT = 1;
    private final int DIR_UP_DOWN = 2;

    private int mTouchSlop;
    private int mSlideMinX;
    private int mLastMotionX;
    private int mDownMotionX;
    private int mDownMotionY;
    private int mCurrentPage = PAGE_NORMAL;
    private int mBeingDragged = DIR_UNKNOWN;
    private boolean mIsMoveEnabled = false;
    private boolean mIsScrollTouchEnabled = false;

    private final int mScreenWidth;
    private final int mScreenHeight;
    private final int mValidScrollMaxY;
    private final Scroller mScroller;


    public IpKeyguardScrollView(Context context) {
        this(context, null, 0);
    }

    public IpKeyguardScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IpKeyguardScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mScreenWidth = Constants.screenWidth;
        mScreenHeight = Constants.screenHeight;
        mValidScrollMaxY = mScreenHeight - (int) (90 * Constants.screenDensity);
        mSlideMinX = (int) (70 * Constants.screenDensity);

        final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = configuration.getScaledTouchSlop();

        mScroller = new Scroller(context);
        mScroller.startScroll(getScrollX(), 0, Constants.screenWidth, 0, 0);
        invalidate();
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), 0);
            postInvalidate();
        }
    }

    public void setOnPageChangedListener(OnPageChangedListener listener) {
        mPageChangedListener = listener;
    }

    public void setScrollTouchEnable(MotionEvent event, boolean en) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            float y = event.getRawY();
            if (y < mValidScrollMaxY) {
                mIsScrollTouchEnabled = en;
            } else {
                mIsScrollTouchEnabled = false;
            }
        }
    }

    public void resetViews() {
        mIsMoveEnabled = false;
        mIsScrollTouchEnabled = false;
        snapToCenterScreen();
    }

    public void postTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        final int x = (int) ev.getRawX();
        final int y = (int) ev.getRawY();

        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                mBeingDragged = 0;
                mLastMotionX = x;
                mDownMotionX = x;
                mDownMotionY = y;
                if (mCurrentPage == 0) {
                    mIsMoveEnabled = true;
                } else {
                    mIsMoveEnabled = y < mValidScrollMaxY;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mCurrentPage == 0 || (mIsMoveEnabled && mIsScrollTouchEnabled)) {
                    int deltaX = mLastMotionX - x;
                    int deltaY = mDownMotionY - y;
                    if (mBeingDragged == DIR_UNKNOWN && (Math.abs(deltaX) > mTouchSlop || Math.abs(deltaY) > mTouchSlop)) {
                        if (Math.abs(deltaX) > Math.abs(deltaY)) {
                            mBeingDragged = DIR_LEFT_RIGHT;
                        } else {
                            mBeingDragged = DIR_UP_DOWN;
                        }
                    }
                    if (mBeingDragged == DIR_LEFT_RIGHT && deltaX != 0) {
                        mLastMotionX = x;
                        if (getScrollX() + deltaX <= 0) {
                            scrollTo(0, 0);
                        } else {
                            scrollBy(deltaX, 0);
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (mBeingDragged == DIR_LEFT_RIGHT && mIsMoveEnabled) {
                    int moveX = mDownMotionX - x;
                    if (Math.abs(moveX) > mSlideMinX) {
                        if (moveX < 0) {
                            snapToScreen(mCurrentPage - 1, true);
                        } else {
                            snapToScreen(mCurrentPage + 1, true);
                        }
                    } else {
                        snapToScreen(mCurrentPage, true);
                    }
                }
                mIsMoveEnabled = false;
                mIsScrollTouchEnabled = false;
                break;
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mPageChangedListener != null) {
            mPageChangedListener.onScrollChanged(Constants.screenWidth, Constants.screenHeight, l, mCurrentPage);
        }
    }

    public void snapToCenterScreen() {
        if (mCurrentPage != PAGE_NORMAL) {
            snapToScreen(PAGE_NORMAL, false);
        }
    }

    public void snapToScreen(int whichScreen, boolean needSpeed) {
        mCurrentPage = whichScreen;
        if (mCurrentPage > PAGE_CAMERA) {
            mCurrentPage = PAGE_CAMERA;
        } else if (mCurrentPage < PAGE_WIDGET) {
            mCurrentPage = PAGE_WIDGET;
        }
        int dx = mCurrentPage * getWidth() - getScrollX();
        if (mCurrentPage == PAGE_CAMERA) {
            postDelayed(mOpenCameraRunnable, 200);
            mScroller.startScroll(getScrollX(), 0, dx, 0, 0);
        } else {
            mScroller.startScroll(getScrollX(), 0, dx, 0, needSpeed ? (int) (Math.abs(dx) * 0.9f) : 0);
        }
        invalidate();
    }

    private final Runnable mOpenCameraRunnable = new Runnable() {

        @Override
        public void run() {
            if (mPageChangedListener != null) {
                mPageChangedListener.onStartCamera();
            }
        }
    };

    public interface OnPageChangedListener {

        void onStartCamera();

        void onScrollChanged(int width, int height, int l, int page);
    }
}
